<?php
namespace store\oss;

if (is_file(__DIR__ . '/../../vendor/autoload.php')) {
    require_once __DIR__ . '/../../vendor/autoload.php';
}

use OSS\Core\OssException;
use OSS\OssClient;
use store\oss\OSSConfig;

/*
 文件续传对象。负责将文件块写到服务器指定目录中
 https://help.aliyun.com/document_detail/32100.html
 
 更新记录：
 2022-10-29 创建
 */
class OSSTool
{
    function __construct()
    {
    }

    public static function client(){
        $cfg = new OSSConfig();
        try {
            // true为开启CNAME。CNAME是指将自定义域名绑定到存储空间上。
            $c = new OssClient($cfg->ak, $cfg->sk, $cfg->endpoint);
            return $c;
        } catch (OssException $e) {
            print $e->getMessage();
        }
    }
    
    /*
     参考：https://help.aliyun.com/document_detail/32100.html
     $key guid/filename     
     */
    public static function putObject(/*string*/$key,$data)
    {
        $cfg = new OSSConfig();
        $c = $this->client();
        try{
            
            $c->pubObject($cfg->bucket,$key,$data);
            return "";
        }
        catch(OssException $e){
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            return;            
        }
    }

    /**
     * 参考：https://help.aliyun.com/document_detail/88497.html
     */
    public static function getObject($key,$blockOffset,$blockLen)
    {
        $cfg = new OSSConfig();        
        try{
            $c = OSSTool::client();
            $range = (string)$blockOffset."-" . (string)($blockOffset+$blockLen-1);
            $options = array(OssClient::OSS_RANGE => $range);
            
            $data = $c->getObject($cfg->bucket, $key,$options);
            return $data;
        } catch(OssException $e) {
            printf(__FUNCTION__ . ": FAILED\n");
            printf($e->getMessage() . "\n");
            throw new \Exception("oss get object error");
        }        
    }

    /**
     * 参考：https://help.aliyun.com/document_detail/88477.html?spm=a2c4g.11186623.0.0.7b6240c2S2aHjU
     */
    public static function createMultipartUpload($key)
    {
        $cfg = new OSSConfig();
        
        try{
            $c = OSSTool::client();
            //返回uploadId。uploadId是分片上传事件的唯一标识，您可以根据uploadId发起相关的操作，如取消分片上传、查询分片上传等。
            $uploadId = $c->initiateMultipartUpload($cfg->bucket, $key);
            return $uploadId;
        } catch(OssException $e) {
            printf(__FUNCTION__ . ": initiateMultipartUpload FAILED\n");
            printf($e->getMessage() . "\n");
            throw new \Exception("oss create upload error");
        }        
    }

    /*
     * 上传分片
      参考：https://help.aliyun.com/document_detail/88477.html?spm=a2c4g.11186623.0.0.7b6240c2S2aHjU
     */
    public static function uploadPart(/*FileInf*/$fileSvr,$data)
    {
        $cfg = new OSSConfig();
        
        try{
            $c = OSSTool::client();            
            
            $upOptions = array(
                // 上传文件。
                $c::OSS_FILE_UPLOAD => $fileSvr->blockPath,
                // 设置分片号。
                $c::OSS_PART_NUM => $fileSvr->blockIndex,
                // 指定分片上传起始位置。
                $c::OSS_SEEK_TO => 0,
                // 指定文件长度。
                $c::OSS_LENGTH => strlen($data)
            );
            
            // 上传分片。
            $res[] = $c->uploadPart($cfg->bucket, $fileSvr->ossKey(), $fileSvr->object_id, $upOptions);
            return $res[0];
            
        } catch(OssException $e) {
            printf(__FUNCTION__ . ": uploadPart FAILED\n");
            printf($e->getMessage() . "\n");
            throw new \Exception("oss create upload error");
        }    
    }

    /*
     参考：https://help.aliyun.com/document_detail/88477.html?spm=a2c4g.11186623.0.0.7b6240c2S2aHjU
     */
    public static function completeMultipartUpload(/*FileInf*/$file){
        $parts = array();
        foreach($file->etags() as $b)
        {
            $parts[]=array(
                "ETag"=>$b["etag"],
                "PartNumber"=>$b["blockIndex"]
            );
        }

        try {
            $cfg = new OSSConfig();
            $c = OSSTool::client();
            $c->completeMultipartUpload($cfg->bucket, $file->ossKey(), $file->object_id, $parts);
            return true;
        }  catch(OssException $e) {
            printf(__FUNCTION__ . ": completeMultipartUpload FAILED\n");
            printf($e->getMessage() . "\n");
            throw new \Exception("oss complete error");
        }
    }
}
?>